#!/usr/bin/env python3
"""
ESP32通信模块
用于RK3588与ESP32之间的串口通信
"""

import serial
import time
import threading
import logging
from typing import Optional, Dict, Any

class ESP32Communicator:
    def __init__(self, port: str = '/dev/ttyUSB0', baudrate: int = 115200, timeout: float = 2.0):
        """
        初始化ESP32通信器
        
        Args:
            port: 串口设备路径
            baudrate: 波特率
            timeout: 超时时间(秒)
        """
        self.port = port
        self.baudrate = baudrate
        self.timeout = timeout
        self.serial_conn: Optional[serial.Serial] = None
        self.is_connected = False
        self.lock = threading.Lock()
        
        # 配置日志
        logging.basicConfig(level=logging.INFO)
        self.logger = logging.getLogger(__name__)
        
    def connect(self) -> bool:
        """连接到ESP32"""
        try:
            self.serial_conn = serial.Serial(
                port=self.port,
                baudrate=self.baudrate,
                timeout=self.timeout,
                bytesize=serial.EIGHTBITS,
                parity=serial.PARITY_NONE,
                stopbits=serial.STOPBITS_ONE
            )
            
            # 等待连接稳定
            time.sleep(1)
            
            # 测试连接
            if self.ping():
                self.is_connected = True
                self.logger.info(f"成功连接到ESP32 on {self.port}")
                return True
            else:
                self.logger.error("连接测试失败")
                return False
                
        except Exception as e:
            self.logger.error(f"连接失败: {e}")
            return False
    
    def disconnect(self):
        """断开连接"""
        if self.serial_conn and self.serial_conn.is_open:
            self.serial_conn.close()
            self.is_connected = False
            self.logger.info("已断开ESP32连接")
    
    def send_command(self, command: str, param: str = "") -> Optional[str]:
        """
        发送命令到ESP32
        
        Args:
            command: 命令字符串
            param: 参数字符串
            
        Returns:
            ESP32的响应字符串，失败返回None
        """
        if not self.is_connected or not self.serial_conn:
            self.logger.error("未连接到ESP32")
            return None
            
        with self.lock:
            try:
                # 构造命令
                if param:
                    cmd_str = f"{command}:{param}\n"
                else:
                    cmd_str = f"{command}:\n"
                
                # 发送命令
                self.serial_conn.write(cmd_str.encode())
                self.logger.debug(f"发送命令: {cmd_str.strip()}")
                
                # 读取响应
                response = self.serial_conn.readline().decode().strip()
                self.logger.debug(f"收到响应: {response}")
                
                return response
                
            except Exception as e:
                self.logger.error(f"发送命令失败: {e}")
                return None
    
    def ping(self) -> bool:
        """测试连接"""
        response = self.send_command("PING")
        return response == "OK:PONG"
    
    def get_info(self) -> Optional[Dict[str, str]]:
        """获取ESP32信息"""
        response = self.send_command("INFO")
        if response and response.startswith("OK:"):
            info_str = response[3:]  # 去掉"OK:"
            return {"info": info_str}
        return None
    
    def reset_esp32(self) -> bool:
        """重启ESP32"""
        response = self.send_command("RESET")
        return response == "OK:RESET"
    
    def read_temperature(self) -> Optional[float]:
        """读取温度"""
        response = self.send_command("READ", "TEMP")
        if response and response.startswith("OK:"):
            try:
                return float(response[3:])
            except ValueError:
                return None
        return None
    
    def read_humidity(self) -> Optional[float]:
        """读取湿度"""
        response = self.send_command("READ", "HUMIDITY")
        if response and response.startswith("OK:"):
            try:
                return float(response[3:])
            except ValueError:
                return None
        return None
    
    def read_all_sensors(self) -> Optional[Dict[str, float]]:
        """读取所有传感器数据"""
        response = self.send_command("READ", "ALL")
        if response and response.startswith("OK:"):
            try:
                data_str = response[3:]  # 去掉"OK:"
                # 解析格式: TEMP:25.6,HUMIDITY:60.2
                sensors = {}
                for item in data_str.split(','):
                    key, value = item.split(':')
                    sensors[key.lower()] = float(value)
                return sensors
            except Exception as e:
                self.logger.error(f"解析传感器数据失败: {e}")
                return None
        return None
    
    def set_led(self, state: bool) -> bool:
        """控制LED"""
        param = "LED:ON" if state else "LED:OFF"
        response = self.send_command("SET", param)
        expected = "OK:LED_ON" if state else "OK:LED_OFF"
        return response == expected
    
    def get_gpio_state(self, gpio_num: int) -> Optional[bool]:
        """读取GPIO状态"""
        response = self.send_command("GET", f"GPIO:{gpio_num}")
        if response == "OK:HIGH":
            return True
        elif response == "OK:LOW":
            return False
        return None

# 使用示例
if __name__ == "__main__":
    # 创建通信器实例
    esp32 = ESP32Communicator('/dev/ttyUSB0')
    
    # 连接
    if esp32.connect():
        print("连接成功!")
        
        # 获取信息
        info = esp32.get_info()
        print(f"ESP32信息: {info}")
        
        # 读取传感器
        temp = esp32.read_temperature()
        humidity = esp32.read_humidity()
        print(f"温度: {temp}°C, 湿度: {humidity}%")
        
        # 控制LED
        esp32.set_led(True)
        time.sleep(1)
        esp32.set_led(False)
        
        # 读取所有传感器
        all_data = esp32.read_all_sensors()
        print(f"所有传感器数据: {all_data}")
        
        # 断开连接
        esp32.disconnect()
    else:
        print("连接失败!") 